<?php


namespace App\Services;


use App\Models\Department;
use App\Models\Role;
use App\Models\User;
use App\Service\Service;
use Dingo\Api\Http\Request;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rule;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Class UserService
 * @property integer $keywords
 * @property integer $department_id
 * @property string $username
 * @property string $realname
 * @property string $password
 * @property integer $status
 * @property integer $user_id
 * @property array $roles
 * @package App\Services
 * @author thanatos thanatos915@163.com
 */
class UserService extends Service
{

    /**
     * 用户列表
     * @param Request $request
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     * @author thanatos thanatos915@163.com
     */
    public static function search(Request $request)
    {
        $service = static::loadParams($request, [
            'keywords' => 'string',
            'department_id' => 'numeric'
        ]);

        $query = User::with('department')->where('username', '!=', 'admin')->orderBy('id', 'desc');

        if ($service->keywords) {
            $query->where(function (/** @var Builder $query */$query) use($service) {
                $query->where('username', 'like', '%'. $service->keywords .'%')
                    ->orWhere('realname', 'like', '%'. $service->keywords .'%');
            });
        }

        if ($service->status) {
            $query->where('status', $service->status);
        }

        if ($service->department_id > 0) {
            $query->where('department_id', $service->department_id);
        }

        return $query->paginate();
    }

    /**
     * 用户部门树
     * @return array
     * @author thanatos thanatos915@163.com
     */
    public static function tree()
    {
        $department = Department::get();
        $users = User::whereIn('department_id', $department->modelKeys())->get();
        $tree = static::parseTree($department, $users);
        return $tree;
    }

    /**
     * 创建或删除用户
     * @param Request $request
     * @param int $id
     * @return User|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model
     * @author thanatos thanatos915@163.com
     */
    public static function createAndUpdate(Request $request, $id = 0)
    {
        $service = static::loadParams($request, [
            'department_id' => 'numeric',
            'username' => [
                'required',
                'string',
                Rule::unique('user')->ignore($id)
            ],
            'realname' => 'required|string',
            'password' => 'string',
            'status' => 'numeric',
            'roles' => 'array'
        ]);

        /** @var User $model */
        $model = [];

        if ($id > 0) {
            $model = User::find($id);
        }

        if (empty($model)) {
            $model = new User();
        }

        $model->fill([
            'username' => $service->username,
            'realname' => $service->realname,
            'status' => $service->status,
        ]);

        // 验证部门
        if ($service->department_id > 0) {
            if (!Department::find($service->department_id)->exists()) {
                throw new BadRequestHttpException("所属部门不存在");
            }
            $model->department_id = $service->department_id;
        }

        // 验证密码
        if ($model->id <= 0) {
            if (!$service->password) {
                throw new BadRequestHttpException("用户密码不能为空");
            }
        }

        if ($service->password) {
            $model->password = Hash::make($service->password);
        }

        $model->save();

        // 查询角色
        $roles = Role::whereIn('id', $service->roles)->get();
        $model->syncRoles($roles);
        return $model;
    }

    /**
     * 用户详情
     * @param $id
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model
     * @author thanatos thanatos915@163.com
     */
    public static function show($id)
    {
        /** @var User $user */
        $user = User::with(['department', 'roles'])->find($id);

        if (empty($user)) {
            throw new NotFoundHttpException("用户不存在");
        }

        return $user;
    }

    /**
     * 冻结用户
     * @author thanatos thanatos915@163.com
     */
    public static function freeze(Request $request)
    {
        $service = static::loadParams($request, [
            'user_id' => 'required|numeric'
        ]);

        $user = User::find($service->user_id);
        if (empty($user)) {
            throw new BadRequestHttpException("用户不存在");
        }

        switch ($user->status) {
            case User::STATUS_NORMAL:
                $user->status = User::STATUS_FREEZE;
                break;
            case User::STATUS_FREEZE:
                $user->status = User::STATUS_NORMAL;
                break;
        }

        $user->save();
    }

    /**
     * 删除用户
     * @param $id
     * @throws \Exception
     * @author thanatos thanatos915@163.com
     */
    public static function delete($id)
    {
        $user = User::find($id);
        if (empty($user)) {
            throw new BadRequestHttpException("用户不存在");
        }
        $user->delete();
    }

    /**
     * @param Collection $department
     * @param Collection $users
     * @param int $parent
     * @return array
     * @author thanatos thanatos915@163.com
     */
    protected static function parseTree($department, $users, $parent = 0)
    {
        $res = [];
        $child = $department->where('parent_id', $parent);
        foreach ($child as $de) {
            $tmp = [
                'title' => $de->name,
                'key' => $de->name . '_' . $de->id,
                'value' => $de->name,
                'selectable' => false
            ];
            $children = [];

            // 子部门
            array_push($children, ...static::parseTree($department, $users, $de->id));

            foreach ($users->where('department_id', $de->id) as $user) {
                array_push($children, [
                    'title' => $user->realname,
                    'key' => $user->id,
                    'value' => $user->id,
                    'isLeaf' => true
                ]);
            }
            if (!empty($children)) {
                $tmp['children'] = $children;
            }
            array_push($res, $tmp);
        }
        return $res;
    }

}
